/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 underlay_adv_object_image.h

	$Header: /heroes4/underlay_adv_object_image.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( UNDERLAY_ADV_OBJECT_IMAGE_H_INCLUDED )
#define UNDERLAY_ADV_OBJECT_IMAGE_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <cassert>

#include "simple_adv_object_image.h"
#include "uncopyable.h"

class t_adv_object_image_visitor_24;
class t_underlay_adv_object_image_24;
class t_adv_object_image_visitor;
class t_underlay_adv_object_image;

// ------------------------------------------------------------------------------
// t_underlay_adv_object_subimage_base class template
// ------------------------------------------------------------------------------

template < typename t_base, typename t_image >
class t_underlay_adv_object_subimage_base : public t_base
{
public:
	// Constructor
	explicit t_underlay_adv_object_subimage_base(
		t_image const &	image );

	// Member functions
	virtual int				get_depth_offset() const;
	t_image const &			get_image() const;
	virtual t_screen_rect	get_rect() const;
	virtual t_screen_rect	get_rect( int frame_num ) const;
	virtual bool			is_underlay() const;

private:
	// Data members
	t_image const &	m_image;
};

template < typename t_base, typename t_image >
t_underlay_adv_object_subimage_base< t_base, t_image >::t_underlay_adv_object_subimage_base(
	t_image const & image )
	:	m_image( image )
{
}

template < typename t_base, typename t_image >
int t_underlay_adv_object_subimage_base< t_base, t_image >::get_depth_offset() const
{
	return 0;
}

template < typename t_base, typename t_image >
inline t_image const & t_underlay_adv_object_subimage_base< t_base, t_image >::get_image() const
{
	return m_image;
}

template < typename t_base, typename t_image >
t_screen_rect t_underlay_adv_object_subimage_base< t_base, t_image >::get_rect() const
{
	return m_image.get_rect();
}

template < typename t_base, typename t_image >
t_screen_rect t_underlay_adv_object_subimage_base< t_base, t_image >::get_rect(
	int	frame_num ) const
{
	return m_image.get_rect( frame_num );
}

template < typename t_base, typename t_image >
bool t_underlay_adv_object_subimage_base< t_base, t_image >::is_underlay() const
{
	return true;
}

// ------------------------------------------------------------------------------
// t_underlay_adv_object_subimage_24 class
// ------------------------------------------------------------------------------

class t_underlay_adv_object_subimage_24
	:	public	t_underlay_adv_object_subimage_base<
					t_adv_object_subimage_24,
					t_underlay_adv_object_image_24 >
{
public:
	// Constructor
	explicit t_underlay_adv_object_subimage_24(
		t_underlay_adv_object_image_24 const & image );
};

inline t_underlay_adv_object_subimage_24::t_underlay_adv_object_subimage_24(
	t_underlay_adv_object_image_24 const & image )
	:	t_underlay_adv_object_subimage_base<
			t_adv_object_subimage_24,
			t_underlay_adv_object_image_24 >( image )
{
}

// ------------------------------------------------------------------------------
// t_underlay_adv_object_subimage class
// ------------------------------------------------------------------------------

class t_underlay_adv_object_subimage
	:	public	t_underlay_adv_object_subimage_base<
					t_adv_object_subimage,
					t_underlay_adv_object_image >
{
public:
	// Constructor
	explicit t_underlay_adv_object_subimage(
		t_underlay_adv_object_image const &	image );

	// Member functions
	virtual void	draw_to(
						int						frame_num,
						t_screen_rect const &	source_rect,
						t_abstract_bitmap16 &	dest,
						t_screen_point const &	dest_point,
						int						alpha = 15 ) const;
	virtual void	draw_to(
						int						frame_num,
						t_abstract_bitmap16 &	dest,
						t_screen_point const &	dest_point ) const;
};

inline t_underlay_adv_object_subimage::t_underlay_adv_object_subimage(
	t_underlay_adv_object_image const & image )
	:	t_underlay_adv_object_subimage_base<
			t_adv_object_subimage,
			t_underlay_adv_object_image >( image )
{
}

// ------------------------------------------------------------------------------
// t_underlay_adv_object_image_base class template
// ------------------------------------------------------------------------------

template < typename t_base, typename t_derived, typename t_subimage_arg >
class t_underlay_adv_object_image_base
	:	public t_base,
		private t_uncopyable
{
public:
	// Types
	typedef typename t_base::t_subimage t_subimage;

	// Constructors
	explicit t_underlay_adv_object_image_base( t_derived const & derived );
	template <
		typename	t_other_base,
		typename	t_other_derived,
		typename	t_other_subimage_arg >
	t_underlay_adv_object_image_base(
		t_underlay_adv_object_image_base<
			t_other_base,
			t_other_derived,
			t_other_subimage_arg > const &	other,
		t_derived const &					derived )
		:	t_base( other ),
			m_subimage( derived )
	{
	}
	t_underlay_adv_object_image_base(
		t_underlay_adv_object_image_base const &	other,
		t_derived const &							derived );
	t_underlay_adv_object_image_base(
		t_base const &		base,
		t_derived const &	derived );

	// Member functions
	virtual t_subimage const &	get_subimage( int subimage_num ) const;
	virtual int					get_subimage_count() const;

private:
	// Data members
	t_subimage_arg		m_subimage;
};

template < typename t_base, typename t_derived, typename t_subimage_arg >
inline	t_underlay_adv_object_image_base<
			t_base,
			t_derived,
			t_subimage_arg >::t_underlay_adv_object_image_base(
	t_derived const & derived )
	:	m_subimage( derived )
{
}

template < typename t_base, typename t_derived, typename t_subimage_arg >
inline	t_underlay_adv_object_image_base<
			t_base,
			t_derived,
			t_subimage_arg >::t_underlay_adv_object_image_base(
	t_underlay_adv_object_image_base const &	other,
	t_derived const &							derived )
	:	t_base( other ),
		m_subimage( derived )
{
}

template < typename t_base, typename t_derived, typename t_subimage_arg >
inline	t_underlay_adv_object_image_base<
			t_base,
			t_derived,
			t_subimage_arg >::t_underlay_adv_object_image_base(
		t_base const &		base,
		t_derived const &	derived )
	:	t_base( base ),
		m_subimage( derived )
{
}

template < typename t_base, typename t_derived, typename t_subimage_arg >
typename	t_underlay_adv_object_image_base<
				t_base,
				t_derived,
				t_subimage_arg >::t_subimage const &
t_underlay_adv_object_image_base<
	t_base,
	t_derived,
	t_subimage_arg >::get_subimage(
	int	subimage_num ) const
{
	assert( subimage_num == 0 );
	return m_subimage;
}

template < typename t_base, typename t_derived, typename t_subimage_arg >
int	t_underlay_adv_object_image_base<
		t_base,
		t_derived,
		t_subimage_arg >::get_subimage_count() const
{
	return 1;
}

// ------------------------------------------------------------------------------
// t_underlay_adv_object_image_24 class
// ------------------------------------------------------------------------------

class t_underlay_adv_object_image_24
	:	public	t_underlay_adv_object_image_base<
					t_simple_adv_object_image_24,
					t_underlay_adv_object_image_24,
					t_underlay_adv_object_subimage_24 >
{
public:
	// Constructors
	t_underlay_adv_object_image_24();
	t_underlay_adv_object_image_24(
		t_underlay_adv_object_image_24 const &	other );
	explicit t_underlay_adv_object_image_24(
		t_simple_adv_object_image_24 const &	other );

	// Member functions
	virtual void			accept( t_visitor & visitor );
	virtual void			accept( t_visitor & visitor ) const;
	virtual t_clone_ptr		clone() const;
	virtual t_clone_16_ptr	clone_as_16() const;
	bool					read( std::streambuf & stream );
	bool					read_version( std::streambuf & stream, int version );
	bool					write( std::streambuf & stream ) const;
};

// ------------------------------------------------------------------------------
// t_underlay_adv_object_image class
// ------------------------------------------------------------------------------

class t_underlay_adv_object_image
	:	public	t_underlay_adv_object_image_base<
					t_simple_adv_object_image,
					t_underlay_adv_object_image,
					t_underlay_adv_object_subimage >
{
public:
	// Constructors
	t_underlay_adv_object_image();
	t_underlay_adv_object_image(
		t_underlay_adv_object_image const &	other );
	explicit t_underlay_adv_object_image(
		t_underlay_adv_object_image_24 const &	other );
	explicit t_underlay_adv_object_image(
		t_simple_adv_object_image const &	other );

	// Member functions
	virtual void		accept( t_visitor & visitor );
	virtual void		accept( t_visitor & visitor ) const;
	virtual t_clone_ptr	clone() const;
};

#endif // !defined( UNDERLAY_ADV_OBJECT_IMAGE_H_INCLUDED )
